package main

import (
	"strings"
	"time"

	g "github.com/gosnmp/gosnmp"
)

// snmpConnect 连接 SNMP
func snmpConnect() (*g.GoSNMP, error) {
	v3Parameters := &g.UsmSecurityParameters{
		UserName:                 config.SNMPv3Params.Username,
		AuthenticationPassphrase: config.SNMPv3Params.AuthPassphrase,
		PrivacyPassphrase:        config.SNMPv3Params.PrivacyPassphrase,
	}
	if strings.ToLower(config.SNMPVer) == "v3" {
		v3Parameters.AuthenticationProtocol = parseSNMPv3AuthAlgorithm(config.SNMPv3Params.AuthAlgorithm)
		v3Parameters.PrivacyProtocol = parseSNMPv3PrivacyAlgorithm(config.SNMPv3Params.PrivacyAlgorithm)
	}
	instance := &g.GoSNMP{
		Target:             config.DevIP,
		Port:               config.SNMPPort,
		Community:          config.SNMPCommunity,
		Version:            parseSNMPVersion(config.SNMPVer),
		Timeout:            5 * time.Second,
		SecurityModel:      g.UserSecurityModel,
		MsgFlags:           parseSecurityLevel(config.SNMPv3Params.SecurityLevel),
		SecurityParameters: v3Parameters,
	}

	if err := instance.Connect(); err != nil {
		return nil, err
	}
	return instance, nil
}

func parseSNMPVersion(s string) g.SnmpVersion {
	switch strings.ToLower(s) {
	case "v1":
		return g.Version1
	case "v2c", "v2":
		return g.Version2c
	case "v3":
		return g.Version3
	default:
		return g.Version2c
	}
}

func parseSecurityLevel(s string) g.SnmpV3MsgFlags {
	switch strings.ToLower(s) {
	case "authpriv":
		return g.AuthPriv
	case "authnopriv":
		return g.AuthNoPriv
	default:
		return g.NoAuthNoPriv
	}
}

func parseSNMPv3AuthAlgorithm(s string) g.SnmpV3AuthProtocol {
	switch strings.ToLower(s) {
	case "md5":
		return g.MD5
	case "sha":
		return g.SHA
	case "sha224":
		return g.SHA224
	case "sha256":
		return g.SHA256
	case "sha384":
		return g.SHA384
	case "sha512":
		return g.SHA512
	default:
		return g.NoAuth
	}
}

func parseSNMPv3PrivacyAlgorithm(s string) g.SnmpV3PrivProtocol {
	switch strings.ToLower(s) {
	case "des":
		return g.DES
	case "aes":
		return g.AES
	case "aes192":
		return g.AES192
	case "aes256":
		return g.AES256
	case "aes192c":
		return g.AES192C
	case "aes256c":
		return g.AES256C
	default:
		return g.NoPriv
	}
}
